From b9bbcdfedb86605eca549b340316bf798d9cfceb Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 10 Feb 2005 15:20:15 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.565 (420b7bafUdB4uOmG-Qm1AYMify0jrQ) p2m and m2p tables are now 4 bytes per entry always, even on x86/64. Fixed mapping of m2p table into kernel space on x86/64. Signed-off-by: keir.fraser@cl.cam.ac.uk --- .../arch/xen/kernel/setup.c | 6 ++-- .../include/asm-xen/page.h | 6 ++-- .../include/asm-xen/pgtable-2level.h | 2 +- .../arch/xen/i386/kernel/setup.c | 4 +-- .../arch/xen/kernel/reboot.c | 2 +- .../include/asm-xen/asm-i386/page.h | 6 ++-- .../include/asm-xen/asm-i386/pgtable-2level.h | 2 +- xen/arch/x86/domain.c | 7 +++-- xen/arch/x86/x86_32/domain_build.c | 4 +-- xen/arch/x86/x86_64/domain_build.c | 4 +-- xen/arch/x86/x86_64/mm.c | 31 ++++++++++++------- xen/include/asm-x86/mm.h | 9 +++--- xen/include/asm-x86/shadow.h | 2 +- xen/include/public/arch-x86_32.h | 2 +- xen/include/public/arch-x86_64.h | 2 +- 15 files changed, 48 insertions(+), 41 deletions(-) diff --git a/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c index fcaf2a89de..063b4427df 100644 --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c @@ -60,7 +60,7 @@ static int errno; */ shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; -unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list; +unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list; DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]); DEFINE_PER_CPU(int, nr_multicall_ents); @@ -327,7 +327,7 @@ void __init setup_arch(char **cmdline_p) } #endif - phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list; + phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list; cur_pgd = init_mm.pgd = (pgd_t *)xen_start_info.pt_base; start_pfn = (__pa(xen_start_info.pt_base) >> PAGE_SHIFT) + @@ -382,7 +382,7 @@ void __init setup_arch(char **cmdline_p) { phys_to_machine_mapping = alloc_bootmem_low_pages( max_pfn * sizeof(unsigned long)); - memset(phys_to_machine_mapping, ~0, max_pfn * sizeof(unsigned long)); + memset(phys_to_machine_mapping, ~0, max_pfn * sizeof(unsigned int)); memcpy(phys_to_machine_mapping, (unsigned long *)xen_start_info.mfn_list, xen_start_info.nr_pages * sizeof(unsigned long)); diff --git a/linux-2.4.29-xen-sparse/include/asm-xen/page.h b/linux-2.4.29-xen-sparse/include/asm-xen/page.h index 546cb65b22..78863c36da 100644 --- a/linux-2.4.29-xen-sparse/include/asm-xen/page.h +++ b/linux-2.4.29-xen-sparse/include/asm-xen/page.h @@ -43,9 +43,9 @@ #define copy_user_page(to, from, vaddr) copy_page(to, from) /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ -extern unsigned long *phys_to_machine_mapping; -#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)]) -#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)]) +extern unsigned int *phys_to_machine_mapping; +#define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)])) +#define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)])) static inline unsigned long phys_to_machine(unsigned long phys) { unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT); diff --git a/linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h b/linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h index 9ddd30bf73..fb6644aedf 100644 --- a/linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h +++ b/linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h @@ -69,7 +69,7 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) * require. In all the cases we care about, the high bit gets shifted out * (e.g., phys_to_machine()) so behaviour there is correct. */ -#define INVALID_P2M_ENTRY (~0UL) +#define INVALID_P2M_ENTRY (~0U) #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1))) #define pte_page(_pte) \ ({ \ diff --git a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c index cc3ba24b97..5285439c36 100644 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c @@ -345,7 +345,7 @@ static void __init probe_roms(void) shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; EXPORT_SYMBOL(HYPERVISOR_shared_info); -unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list; +unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list; EXPORT_SYMBOL(phys_to_machine_mapping); DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]); @@ -1142,7 +1142,7 @@ static unsigned long __init setup_memory(void) } #endif - phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list; + phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list; return max_low_pfn; } diff --git a/linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c index 07aae9d0c6..f69db851a4 100644 --- a/linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c @@ -80,7 +80,7 @@ static void __do_suspend(void) extern void time_suspend(void); extern void time_resume(void); extern unsigned long max_pfn; - extern unsigned long *pfn_to_mfn_frame_list; + extern unsigned int *pfn_to_mfn_frame_list; suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL); if ( suspend_record == NULL ) diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h index da282bd498..6215a5b018 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h @@ -55,9 +55,9 @@ #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ -extern unsigned long *phys_to_machine_mapping; -#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)]) -#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)]) +extern unsigned int *phys_to_machine_mapping; +#define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)])) +#define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)])) static inline unsigned long phys_to_machine(unsigned long phys) { unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT); diff --git a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h index c7db3fee59..3abd3ce14a 100644 --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h +++ b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h @@ -92,7 +92,7 @@ static inline pte_t ptep_get_and_clear(pte_t *xp) * require. In all the cases we care about, the high bit gets shifted out * (e.g., phys_to_machine()) so behaviour there is correct. */ -#define INVALID_P2M_ENTRY (~0UL) +#define INVALID_P2M_ENTRY (~0U) #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1))) #define pte_pfn(_pte) \ ({ \ diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 294ed178c1..2ff1455820 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -271,12 +271,12 @@ void arch_do_createdomain(struct exec_domain *ed) ed->vcpu_info = &d->shared_info->vcpu_data[ed->eid]; SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); machine_to_phys_mapping[virt_to_phys(d->shared_info) >> - PAGE_SHIFT] = INVALID_P2M_ENTRY; + PAGE_SHIFT] = INVALID_M2P_ENTRY; d->arch.mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE); machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> - PAGE_SHIFT] = INVALID_P2M_ENTRY; + PAGE_SHIFT] = INVALID_M2P_ENTRY; ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt; #ifdef __x86_64__ @@ -687,7 +687,8 @@ long do_switch_to_user(void) struct switch_to_user stu; struct exec_domain *ed = current; - if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) ) + if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) || + unlikely(pagetable_val(ed->arch.pagetable_user) == 0) ) return -EFAULT; ed->arch.flags &= ~TF_kernel_mode; diff --git a/xen/arch/x86/x86_32/domain_build.c b/xen/arch/x86/x86_32/domain_build.c index b6f8624d06..2c11f71668 100644 --- a/xen/arch/x86/x86_32/domain_build.c +++ b/xen/arch/x86/x86_32/domain_build.c @@ -116,7 +116,7 @@ int construct_dom0(struct domain *d, vinitrd_start = round_pgup(dsi.v_kernend); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); - vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long)); + vphysmap_end = vphysmap_start + (nr_pages * sizeof(u32)); vpt_start = round_pgup(vphysmap_end); for ( nr_pt_pages = 2; ; nr_pt_pages++ ) { @@ -337,7 +337,7 @@ int construct_dom0(struct domain *d, if ( pfn > REVERSE_START ) mfn = (alloc_end>>PAGE_SHIFT) - (pfn - REVERSE_START); #endif - ((unsigned long *)vphysmap_start)[pfn] = mfn; + ((u32 *)vphysmap_start)[pfn] = mfn; machine_to_phys_mapping[mfn] = pfn; } diff --git a/xen/arch/x86/x86_64/domain_build.c b/xen/arch/x86/x86_64/domain_build.c index f84a3e0f9c..bd82b4ef7c 100644 --- a/xen/arch/x86/x86_64/domain_build.c +++ b/xen/arch/x86/x86_64/domain_build.c @@ -119,7 +119,7 @@ int construct_dom0(struct domain *d, vinitrd_start = round_pgup(dsi.v_kernend); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); - vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long)); + vphysmap_end = vphysmap_start + (nr_pages * sizeof(u32)); vpt_start = round_pgup(vphysmap_end); for ( nr_pt_pages = 2; ; nr_pt_pages++ ) { @@ -358,7 +358,7 @@ int construct_dom0(struct domain *d, if ( pfn > REVERSE_START ) mfn = (alloc_end>>PAGE_SHIFT) - (pfn - REVERSE_START); #endif - ((unsigned long *)vphysmap_start)[pfn] = mfn; + ((u32 *)vphysmap_start)[pfn] = mfn; machine_to_phys_mapping[mfn] = pfn; } diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index f69d06a1cf..5bced9a509 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -115,8 +115,8 @@ void __set_fixmap( void __init paging_init(void) { - void *newpt; unsigned long i, p, max; + l3_pgentry_t *l3rw, *l3ro; /* Map all of physical memory. */ max = ((max_page + L1_PAGETABLE_ENTRIES - 1) & @@ -134,25 +134,32 @@ void __init paging_init(void) if ( p == 0 ) panic("Not enough memory for m2p table\n"); map_pages(idle_pg_table, RDWR_MPT_VIRT_START + i*8, p, - 1UL << L2_PAGETABLE_SHIFT, PAGE_HYPERVISOR); + 1UL << L2_PAGETABLE_SHIFT, PAGE_HYPERVISOR | _PAGE_USER); memset((void *)(RDWR_MPT_VIRT_START + i*8), 0x55, 1UL << L2_PAGETABLE_SHIFT); } + /* + * Above we mapped the M2P table as user-accessible and read-writable. + * Fix security by denying user access at the top level of the page table. + */ + idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)] = + mk_l4_pgentry(l4_pgentry_val( + idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]) & + ~_PAGE_USER); + /* Create read-only mapping of MPT for guest-OS use. */ - newpt = (void *)alloc_xenheap_page(); - clear_page(newpt); + l3ro = (l3_pgentry_t *)alloc_xenheap_page(); + clear_page(l3ro); idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)] = - mk_l4_pgentry((__pa(newpt) | __PAGE_HYPERVISOR | _PAGE_USER) & + mk_l4_pgentry((__pa(l3ro) | __PAGE_HYPERVISOR | _PAGE_USER) & ~_PAGE_RW); /* Copy the L3 mappings from the RDWR_MPT area. */ - p = l4_pgentry_val(idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]); - p &= PAGE_MASK; - p += l3_table_offset(RDWR_MPT_VIRT_START) * sizeof(l3_pgentry_t); - newpt = (void *)((unsigned long)newpt + - (l3_table_offset(RO_MPT_VIRT_START) * - sizeof(l3_pgentry_t))); - memcpy(newpt, __va(p), + l3rw = l4_pgentry_to_l3( + idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]); + l3rw += l3_table_offset(RDWR_MPT_VIRT_START); + l3ro += l3_table_offset(RO_MPT_VIRT_START); + memcpy(l3ro, l3rw, (RDWR_MPT_VIRT_END - RDWR_MPT_VIRT_START) >> L3_PAGETABLE_SHIFT); /* Set up linear page table mapping. */ diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 4d36b6c25b..1d0cf33c24 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -128,8 +128,6 @@ static inline u32 pickle_domptr(struct domain *domain) spin_unlock(&(_dom)->page_alloc_lock); \ } while ( 0 ) -#define INVALID_P2M_ENTRY (~0UL) - extern struct pfn_info *frame_table; extern unsigned long frame_table_size; extern unsigned long max_page; @@ -231,15 +229,16 @@ void synchronise_pagetables(unsigned long cpu_mask); * contiguous (or near contiguous) physical memory. */ #undef machine_to_phys_mapping +#define machine_to_phys_mapping ((u32 *)RDWR_MPT_VIRT_START) +#define INVALID_M2P_ENTRY (~0U) +#define IS_INVALID_M2P_ENTRY(_e) (!!((_e) & (1U<<31))) /* * The phys_to_machine_mapping is the reversed mapping of MPT for full * virtualization. */ -#undef phys_to_machine_mapping - -#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START) #define __phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START) + /* Returns the machine physical */ static inline unsigned long phys_to_machine_mapping(unsigned long pfn) { diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 15858d5901..62e30cd328 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -181,7 +181,7 @@ static inline int __mark_dirty(struct domain *d, unsigned int mfn) * domain's pseudo-physical memory map (e.g., the shared info frame). * Nothing to do here... */ - if ( unlikely(pfn & 0x80000000UL) ) + if ( unlikely(IS_INVALID_M2P_ENTRY(pfn)) ) return rc; if ( likely(pfn < d->arch.shadow_dirty_bitmap_size) ) diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 524138fd09..65abc26efb 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -71,7 +71,7 @@ */ #define HYPERVISOR_VIRT_START (0xFC000000UL) #ifndef machine_to_phys_mapping -#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) +#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START) #endif #ifndef __ASSEMBLY__ diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 3f14c3a809..aba053181e 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -81,7 +81,7 @@ /* The machine->physical mapping table starts at this address, read-only. */ #ifndef machine_to_phys_mapping -#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) +#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START) #endif /* -- 2.30.2